# -*- coding: UTF8 -*-
# -*- coding: UTF8 -*-
import random
import string

from xmpp import *
from Queue import *
import Unit
import DF
import Behaviour
import ACLMessage
import Agent
import AID
import OrganizationalExceptions

class OrganizationalUnit:

    def __init__(self,agent,name, type, parent,goalList=None,contentLanguage="sl"):
        self.myAgent=agent
        self.muc_name = self.myAgent.getMUC()
        self.platform=self.muc_name.split("muc.")[1]
        self.name = name.lower()
        self.nick =self.myAgent.getAID().getName().split("@")[0]
        self.type = type
        self.goalList = goalList
        self.contentLanguage = contentLanguage
        self.parent=parent.lower()
        self.members=[]
        self.norms=[]
        self.role=[]
        self.unitList=[]

#funciones básicas
    def getUnitID(self):
        return self.name
    def getType(self):
        return self.type
    def getParent(self):
        return self.parent
    def getMemberList(self):
        return self.members
    def getRoleList(self):
        return self.role
    def getNormList(self):
        return self.norm
    def getUnitList(self):
        return self.unitList
    def appendUnit(self,unitID):
        self.unitList.append(unitID)
    def getInfo(self):
        return str(self.name)+","+str(self.parent)+","+str(self.unitList)
#REGISTER UNIT
    def registerUnit(self):
        if not self.testRoomName():
          return False
        elif not self.createRoom():
          return False
        else:
          return True

    def createRoom(self):
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        p = Presence(frm=self.name+"@"+self.muc_name+"/"+self.nick)
        t1 = Behaviour.MessageTemplate(p)
        b=self.CreateRoomBehaviour(ID,self.muc_name,self.name,self.nick)
        self.myAgent.addBehaviour(b, t1)
        b.join()
        return b.result

    class CreateRoomBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,ID,muc_name,roomname,nick):
            Behaviour.OneShotBehaviour.__init__(self)
            self.result = False
            self.ID=ID
            self.nick=nick
            self.muc_name=muc_name
            self.name=roomname

        def _process(self):
            p = Presence(to=self.name+"@"+self.muc_name+"/"+self.nick)
            x = Protocol("x", xmlns="http://jabber.org/protocol/muc")
            p.addChild(node=x)
            self.myAgent.jabber.send(p)
            msg=self._receive(True,10)
            if msg:
                if msg.getAttr("type")=="error":
                    print "Room creation is restricted"
                    self.result= False
                    return
            else:
                    self.result= False
                    return
            template= Iq(frm=self.name+"@"+self.muc_name, attrs={"id":self.ID})
            t = Behaviour.MessageTemplate(template)
            self.setTemplate(t)
            iq = Iq(to=self.name+"@"+self.muc_name,typ='set', attrs={"id":self.ID})
            query = Protocol('query',xmlns="http://jabber.org/protocol/muc#owner")
            x=Node(tag="x", attrs={"xmlns":"jabber:x:data"," type":"submit"})
            query.addChild(node=x)
            iq.addChild(node=query)
            self.myAgent.jabber.send(iq)
            msg = self._receive(True,10)
            #para descartar los presence anteriores
            while msg and msg.getName()!="iq":
                msg = self._receive(True,10)
            if msg and msg.getAttr("type")=="result":
                self.result= True
            else:
                self.result= False

    def testRoomName(self):
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        iq = Iq(frm=self.muc_name, attrs={"id":ID})
        t = Behaviour.MessageTemplate(iq)
        b=self.TestRoomNameBehaviour(ID,self.muc_name,self.name)
        self.myAgent.addBehaviour(b, t)
        b.join()
        return b.result

    class TestRoomNameBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,ID,muc_name,roomname):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.result = False
            self.muc_name=muc_name
            self.roomname=roomname

        def _process(self):
           iq = Iq(to=self.muc_name,typ='get', attrs={"id":self.ID})
           query = Protocol('query',xmlns="http://jabber.org/protocol/disco#items")
           iq.addChild(node=query)
           self.myAgent.jabber.send(iq)
           msg = self._receive(True,10)
           if msg:
               if query:
                   self.result = True
                   items = msg.getQueryChildren()
                   for item in items:
                       if item.getAttr("jid") == str(self.roomname+"@"+self.muc_name):
                           self.result = False
               else:
                   self.result = False
# DEREGISTERUNIT
    def deregisterUnit(self):
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        iq = Iq(frm=self.muc_name, attrs={"id":ID})
        t = Behaviour.MessageTemplate(iq)
        b=self.DestroyBehaviour(ID,self.muc_name,self.name)
        self.myAgent.addBehaviour(b, t)

    class DestroyBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,ID,muc_name,roomname):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.muc_name=muc_name
            self.name=roomname

        def _process(self):
          iq = Iq(to=self.name+"@"+self.muc_name,typ='set', attrs={"id":self.ID})
          query = Protocol('query',xmlns="http://jabber.org/protocol/muc#owner")
          item= Node(tag="destroy")
          query.addChild(node=item)
          iq.addChild(node=query)
          self.myAgent.jabber.send(iq)

"""
    def myCreate(self):
      if not self.testRoomName():
          return OrganizationalException.NotValidName
      else:
          orgManager=OrgManager(name=self.name+"@"+self.platform,orgName=self.name,type=self.type,goalList = self.goalList,contentLanguage = self.contentLanguage,muc_name=self.muc_name,parent=self.parent)
          orgManager.start()
          r=orgManager.myCreate()
          if r:
              return r
              orgManager._shutdown()
          else:
              self.orgManager=orgManager.getAID()
              return True

    def myJoin(self):
      code=self.myJoinRoom()
      if code!=True:
                if code=="401":
                    return OrganizationalException.PasswordNeeded
                if code=="407":
                    return OrganizationalException.MembersOnly
                if code=="403":
                    return OrganizationalException.BanedUser
                if code=="409":
                    return OrganizationalException.NickNameConflict
                if code=="503":
                    return OrganizationalException.MaximumUsers
                if code=="404":
                    return OrganizationalException.LockedOrganization
      else:
          self.state="available"
          self.orgManager=AID.aid(self.name+"@"+self.platform,["xmpp://"+self.name+"@"+self.platform])
          return True

    def myJoinRoom(self):
        p = Presence(frm=self.name+"@"+self.muc_name+"/"+self.nick,attrs={"type":"error"})
        t1 = Behaviour.MessageTemplate(p)
        b=self. MyJoinRoomBehaviour(self.muc_name,self.name,self.nick)
        self.myAgent.addBehaviour(b, t1)
        b.join()
        return b.result

    class  MyJoinRoomBehaviour(Behaviour.OneShotBehaviour):
            def __init__(self,muc_name,roomname,nick):
                Behaviour.OneShotBehaviour.__init__(self)
                self.result = False
                self.nick=nick
                self.muc_name=muc_name
                self.name=roomname


            def _process(self):
                p = Presence(to=self.name+"@"+self.muc_name+"/"+self.nick)
                x = Protocol("x", xmlns="http://jabber.org/protocol/muc")
                p.addChild(node=x)
                self.myAgent.jabber.send(p)
                msg=self._receive(True,1)
                if msg:
                        error=msg.getTag("error")
                        if error:
                            self.result = error.getAttr("code")
                            return
                self.result = True


    def testRoomName(self):
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        iq = Iq(frm=self.muc_name, attrs={"id":ID})
        t = Behaviour.MessageTemplate(iq)
        b=self.TestRoomNameBehaviour(ID,self.muc_name,self.name)
        self.myAgent.addBehaviour(b, t)
        b.join()
        return b.result

    class TestRoomNameBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,ID,muc_name,roomname):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.result = False
            self.muc_name=muc_name
            self.roomname=roomname

        def _process(self):
           iq = Iq(to=self.muc_name,typ='get', attrs={"id":self.ID})
           query = Protocol('query',xmlns="http://jabber.org/protocol/disco#items")
           iq.addChild(node=query)
           self.myAgent.jabber.send(iq)
           msg = self._receive(True,10)
           if msg:
               if query:
                   self.result = True
                   items = msg.getQueryChildren()
                   for item in items:
                       if item.getAttr("jid") == str(self.roomname+"@"+self.muc_name):
                           self.result = False
               else:
                   self.result = False
#FUNCIONES DE CONFIGURACIÓN
    def addRole(self,rol,parent=[]):
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        id="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        mens=Behaviour.ACLTemplate()
        mens.setPerformative("inform")
        mens.setOntology("x:spade:organization")
        mens.setConversationId(id)
        t = Behaviour.MessageTemplate(mens)
        b=self.RoleBehaviour(self.orgManager,id,"Add",rol,parent)
        self.myAgent.addBehaviour(b, t)
        b.join()
        return b.result

    def getRoleList(self):
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        id="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        mens=Behaviour.ACLTemplate()
        mens.setPerformative("inform")
        mens.setOntology("x:spade:organization")
        mens.setConversationId(id)
        t = Behaviour.MessageTemplate(mens)
        b=self.RoleBehaviour(self.orgManager,id,"Get")
        self.myAgent.addBehaviour(b, t)
        b.join()
        return b.result

    def removeRole(self,rol):
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        id="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        mens=Behaviour.ACLTemplate()
        mens.setPerformative("inform")
        mens.setOntology("x:spade:organization")
        mens.setConversationId(id)
        t = Behaviour.MessageTemplate(mens)
        b=self.RoleBehaviour(self.orgManager,id,"Remove",rol)
        self.myAgent.addBehaviour(b, t)
        b.join()
        return b.result

    class RoleBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,aid,id,type,rol=None,parent=None):
            Behaviour.OneShotBehaviour.__init__(self)
            self.aid=aid
            self.id=id
            self.rol=rol
            self.parent=parent
            self.type=type
            self.result = False

        def _process(self):
            #envia un msg al manager solicitando el cambio
            if self.type=="Add" and self.rol!=None:
                mens=ACLMessage.ACLMessage()
                mens.setPerformative("request")
                mens.setSender(self.myAgent.getAID())
                mens.addReceiver(self.aid)
                mens.setConversationId(self.id)
                mens.setContent("Role:Add:"+str(self.rol)+":"+str(self.parent))
                mens.setOntology("x:spade:organization")
                self.myAgent.send(mens)
                ans=self._receive(True,20)
                if ans and ans.getContent()=="Agree":
                    self.result=True
            if self.type=="Get":
                mens=ACLMessage.ACLMessage()
                mens.setPerformative("request")
                mens.setSender(self.myAgent.getAID())
                mens.addReceiver(self.aid)
                mens.setConversationId(self.id)
                mens.setContent("Role:Get")
                mens.setOntology("x:spade:organization")
                self.myAgent.send(mens)
                ans=self._receive(True,20)
                if ans and ans.getContent()!="Not Agree":
                    self.result=ans.getContent()
            if self.type=="Remove" and self.rol!=None:
                mens=ACLMessage.ACLMessage()
                mens.setPerformative("request")
                mens.setSender(self.myAgent.getAID())
                mens.addReceiver(self.aid)
                mens.setConversationId(self.id)
                mens.setContent("Role:Remove:"+str(self.rol))
                mens.setOntology("x:spade:organization")
                self.myAgent.send(mens)
                ans=self._receive(True,20)
                if ans and ans.getContent()=="Agree":
                    self.result=True


    #Faltan las funciones de las misiones/reglas etc
    def setGoal(self,goal):
        \"""
        Updates unit's goal
          \"""
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        if not checkGoal(goal):
            raise OrganizationalException.NotValidGoal
            return
        if not self.askManager("Goal"):
            raise OrganizationalException.NotAllowed
            return
        m = Message(to=self.name+"@"+self.muc_name, typ="groupchat")
        sub = Node(tag="subject")
        sub.addData(str(goal))
        m.addChild(node=sub)
        self.myAgent.jabber.send(m)

#FUNCIONES DINAMMICAS
    def leave(self):
        \"""
         Agent leaves and it is removed from the member list
          \"""
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        #falta  la parte de salir de las unidades
        p = Presence(to=self.name+"@"+self.muc_name+"/"+self.nick,typ="unavailable")
        self.myAgent.jabber.send(p)
        self.myAgent.removeBehaviour(self)
        self.state="unavailable"

    def destroy(self):
        #se tiene que solicitar al OrgManager
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        if not self.askManager("Destroy"):
            raise OrganizationalException.NotAllowed
            return
        self.state="unavailable"
        self.myAgent.removeBehaviour(self)

    def addUnit(self,name,type):
        #se tiene que solicitar al OrgManager
        \"""
          Creates a new unit inside an organization
          \"""
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        if not checkTypes(self.type,type):
            raise OrganizationalException.NotValidType
            return
        if not self.askManager("Creation"):
            raise OrganizationalException.NotAllowed
            return
        unit=NewUnit.NewUnit(self.myAgent,name=name,type=type,parent=self.name)
        r=unit.myCreate()
        if r!=True:
            raise r
        else:
            return True


    def joinUnit(self,name,nick=None):
        if self.state=="unavailable":
            raise OrganizationalException.Unavailable
            return
        if name not in self.getUnitList():
            raise OrganizationalException.NotValidName
            return
        info=self.getUnitInfo(name)
        while not info:
            self.getUnitInfo(name)
        type=info["type"]
        if not nick:
            nick=self.myAgent.getAID().getName().split("@")[0]
        \"""if type=="Flat":
            organization=Organization.Flat(self,nick,name)
        elif type=="Team":
            organization=Organization.Team(self,nick,name)
        elif type=="Hierarchy":
            organization=Organization.Hierarchy(self,nick,name)
        elif type=="Federation":
            organization=Organization.Federation(self,nick,name)
        elif type=="Matrix":
            organization=Organization.Matrix(self,nick,name)
        elif type=="Bureaucracy":
            organization=Organization.Bureaucracy(self,nick,name)
        elif type=="Coalition":
            organization=Organization.Coalition(self,nick,name)
        elif type=="Congregation":
            organization=Organization.Congregation(self,nick,name)
        else:\"""
        unit=NewUnit.NewUnit(self.myAgent,nick=nick,name=name,type=type,parent=self.name)
        result=unit.myJoin()
        if result==True:
            self.myAgent.addBehaviour(unit)
            return unit
        else:
            raise result






#FUNCIONES INFORMATIVAS
    def getUnitList(self):
      \"""
      Returns a list of the units
      \"""
      if self.state=="unavailable":
        raise OrganizationalException.Unavailable
        return
      l=[]
      dad = DF.DfAgentDescription()
      ds = DF.ServiceDescription()
      ds.setType("UNIT")
      dad.addService(ds)
      parent=self.name
      cont=1
      search = self.myAgent.searchService(dad)
      while cont<=3 and not search:
          cont=cont+1
          search = self.myAgent.searchService(dad)
      if search:
          for d in search:
              for s in d.getServices():
                  prop=s.getProperties()
                  for p in prop:
                      if p["name"].strip("u'")=="parent" and p["value"].strip("u'")==parent:
                          l.append(str(s.getName()))
      return l

    def getUnitInfo(self,unitname):
      \"""returns info about the unit unitname\"""
      if self.state=="unavailable":
        raise OrganizationalException.Unavailable
        return
      if unitname not in self.getUnitList():
          raise OrganizationalException.NotValidUnit
          return
      ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
      p = Iq(frm=unitname+"@"+self.muc_name,typ='result', attrs={"id":ID})
      t1 = Behaviour.MessageTemplate(p)
      b=self.GetInfoBehaviour(self.muc_name,unitname,ID)
      self.myAgent.addBehaviour(b, t1)
      b.join()
      d=b.result
      return d


    class GetInfoBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,muc_name,roomname,ID):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.muc_name=muc_name
            self.name=roomname
            self.result=None

        def _process(self):
          info={}
          iq = Iq(to=self.name+"@"+self.muc_name,typ='get', attrs={"id":self.ID})
          query = Protocol('query',xmlns="http://jabber.org/protocol/disco#info")
          iq.addChild(node=query)
          self.myAgent.jabber.send(iq)
          msg=self._receive(True,10)
          if msg:
            query = msg.getTag("query")
            if query:
              x = query.getTag("x")
              if x:
                  items =x.getChildren()
                  for item in items:
                    if item.getAttr("var")=="muc#roominfo_description":
                        if item.getTags("value"):
                            info["type"]=str(item.getTags("value")[0].getData())
                    if item.getAttr("var")=="muc#roominfo_subject":
                        if item.getTags("value"):
                            info["goal"]=str(item.getTags("value")[0].getData())
                    if item.getAttr("var")=="muc#roominfo_type":
                        if item.getTags("value")[0].getData():
                            info["parent"]= str(item.getTags("value")[0].getData().split(":"+self.name)[0])
                    if item.getAttr("var")=="muc#roominfo_lang":
                        if item.getTags("value"):
                            info["contentLanguage"]=str(item.getTags("value")[0].getData())
          self.result=info

    def getGoal(self):
      \"""
      Returns a list of goals
      \"""
      if self.state=="unavailable":
        raise OrganizationalException.Unavailable
        return
      ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
      p = Iq(frm=self.name+"@"+self.muc_name,typ='result', attrs={"id":ID})
      t1 = Behaviour.MessageTemplate(p)
      b=self.GetGoalBehaviour(self.muc_name,self.name,ID)
      self.myAgent.addBehaviour(b, t1)
      b.join()
      return b.result


    class GetGoalBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,muc_name,roomname,ID):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.muc_name=muc_name
            self.name=roomname
            self.result=None

        def _process(self):
          goal=None
          iq = Iq(to=self.name+"@"+self.muc_name,typ='get', attrs={"id":self.ID})
          query = Protocol('query',xmlns="http://jabber.org/protocol/disco#info")
          iq.addChild(node=query)
          self.myAgent.jabber.send(iq)
          msg=self._receive(True,10)
          if msg:
            query = msg.getTag("query")
            if query:
              x = query.getTag("x")
              if x:
                  items =x.getChildren()
                  for item in items:
                    if item.getAttr("var")=="muc#roominfo_subject":
                        if item.getTags("value"):
                            goal=item.getTags("value")[0].getData()
          if goal==None:
            print "Not goal"
          self.result=goal
#FUNCIONES AUXILIARES

    def askManager(self,question):
        id="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        mens=Behaviour.ACLTemplate()
        mens.setPerformative("inform")
        mens.setOntology("x:spade:organization")
        mens.setConversationId(id)
        t = Behaviour.MessageTemplate(mens)
        b=self.AskManagerBehaviour(question,id,self.orgManager)
        self.myAgent.addBehaviour(b,t)
        b.join()
        return b.result

    class AskManagerBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,question,id,aid):
            Behaviour.OneShotBehaviour.__init__(self)
            self.question=question
            self.id=id
            self.aid=aid
            self.result=False
        def _process(self):
            mens=ACLMessage.ACLMessage()
            mens.setPerformative("request")
            mens.setOntology("x:spade:organization")
            mens.setConversationId(self.id)
            mens.setContent("Permision:"+str(self.question))
            mens.setSender(self.myAgent.getAID())
            mens.addReceiver(self.aid)
            self.myAgent.send(mens)
            ans=self._receive(True,20)
            if ans:
                if ans.getContent()=="Agree":
                    self.result=True
                elif ans.getContent()=="Not Agree":
                    self.result=False
                else:
                    self.result=eval(ans.getContent())

    def _process(self):
        pass



class OrgManager(Agent.Agent):

    def __init__(self,name,orgName, type,goalList,contentLanguage,muc_name,parent):
        Agent.Agent.__init__(self,name,"pass")
        self.name = orgName
        self.muc_name=muc_name
        self.type = type
        self.goalList = goalList
        self.contentLanguage = contentLanguage
        self.nick="agentManager"
        self.parent=parent
        self.roleList=[]
        self.orgRoleList=self.roleList
        self.agentList=[]
        self.unitList=[]

    def _setup(self):
        mens=Behaviour.ACLTemplate()
        mens.setPerformative("request")
        mens.setOntology("x:spade:organization")
        t = Behaviour.MessageTemplate(mens)
        self.addBehaviour(self.AnsweringBehaviour(),t)

        p = Presence(frm=self.name+"@"+self.muc_name)
        t = Behaviour.MessageTemplate(p)
        self.addBehaviour(self.PresenceBehaviour(), t)

        mens=Behaviour.ACLTemplate()
        mens.setOntology("x:spade:manager")
        t = Behaviour.MessageTemplate(mens)
        self.addBehaviour(self.ManagerBehaviour(),t)

    class AnsweringBehaviour(Behaviour.Behaviour):
        def __init__(self):
            Behaviour.Behaviour.__init__(self)

        def _process(self):
            #¿Quien puede modificarla?????
            mens=self._receive(True,1)
            if mens and mens.getPerformative()=="request":
                ans=ACLMessage.ACLMessage()
                ans.setPerformative("inform")
                ans.setSender(self.myAgent.getAID())
                ans.addReceiver(mens.getSender())
                ans.setConversationId(mens.getConversationId())
                ans.setOntology("x:spade:organization")
                ans.setContent("Not Agree")
                content=mens.getContent().split(":")
                if content[0]=="Role":
                    if content[1]=="Add":
                        roleName=str(content[2])
                        parent=eval(str(content[3]))
                        if(self.myAgent.allow("Role","Add",roleName,parent)):
                            ans.setContent("Agree")
                    elif content[1]=="Get":
                        if(self.myAgent.allow("Role","Get")):
                            ans.setContent(str(self.myAgent.roleList))
                    elif content[1]=="Remove":
                        roleName=str(content[2])
                        if(self.myAgent.allow("Role","Remove",roleName)):
                            ans.setContent("Agree")
                if content[0]=="RoleLink":
                    if content[1]=="Add":
                        rol1=str(content[2])
                        rol2=str(content[3])
                        type=str(content[4])
                        if(self.myAgent.allow("RoleLink","Add",rol1,rol2,type)):
                            ans.setContent("Agree")
                    elif content[1]=="Get":
                        if(self.myAgent.allow("RoleLink","Get")):
                            ans.setContent(str(self.myAgent.roleLinkList))
                    elif content[1]=="Remove":
                        rol1=str(content[2])
                        rol2=str(content[3])
                        if(self.myAgent.allow("RoleLink","Remove",rol1,rol2)):
                            ans.setContent("Agree")
                if content[0]=="CardinalityConstraint":
                    if content[1]=="Add":
                        rol=str(content[2])
                        min=str(content[3])
                        max=str(content[4])
                        if(self.myAgent.allow("CardinalityConstraint","Add",rol,min,max)):
                            ans.setContent("Agree")
                    elif content[1]=="Get":
                        if(self.myAgent.allow("CardinalityConstraint","Get")):
                            ans.setContent(str(self.myAgent.cardinalityConstraintList))
                    elif content[1]=="Remove":
                        rol=str(content[2])
                        if(self.myAgent.allow("CardinalityConstraint","Remove",rol)):
                            ans.setContent("Agree")
                if content[0]=="CompatibilityConstraint":
                    if content[1]=="Add":
                        rol1=str(content[2])
                        rol2=str(content[3])
                        if(self.myAgent.allow("CompatibilityConstraint","Add",rol1,rol2)):
                            ans.setContent("Agree")
                    elif content[1]=="Get":
                        if(self.myAgent.allow("CompatibilityConstraint","Get")):
                            ans.setContent(str(self.myAgent.compatibilityConstraintList))
                    elif content[1]=="Remove":
                        rol1=str(content[2])
                        rol2=str(content[3])
                        if(self.myAgent.allow("CompatibilityConstraint","Remove",rol1,rol2)):
                            ans.setContent("Agree")
                if content[0]=="Permision":
                    action=str(content[1])
                    if action=="PlayRole":
                        info=str(content[2])
                        agent=mens.getSender().getName()
                        if self.myAgent.allow("Permision",action,info,agent):
                            ans.setContent("Agree")
                    elif action=="GiveRoleUp":
                        info=str(content[2])
                        agent=mens.getSender().getName()
                        if self.myAgent.allow("Permision",action,info,agent):
                            ans.setContent("Agree")
                    elif action=="Member":
                        role=str(content[2])
                        agent=mens.getSender().getName()
                        ans.setContent(str(self.myAgent.allow("Permision",action,role,agent)))
                    elif action=="Number":
                        role=str(content[2])
                        agent=mens.getSender().getName()
                        ans.setContent(str(self.myAgent.allow("Permision",action,role,agent)))
                    elif action=="Communication":
                        role=str(content[2])
                        agent=mens.getSender().getName()
                        ans.setContent(str(self.myAgent.allow("Permision",action,role,agent)))
                    else:
                        if self.myAgent.allow("Permision",action):
                            ans.setContent("Agree")
                self.myAgent.send(ans)



    def myCreate(self):
      if not checkGoal(self.goalList):
          return OrganizationalException.NotValidGoal
      elif not checkType(self.type):
          return OrganizationalException.NotValidType
      elif not self.createRoom():
          return OrganizationalException.CreationError
      else:
     #registrando en el DF
          dad = DF.DfAgentDescription()
          dad.setAID(self.getAID())
          ds = DF.ServiceDescription()
          ds.setType("ORGANIZATION")
          ds.setName(self.name)
          dad.addService(ds)
          res = self.registerService(dad)
          cont=0
          while not res and cont<3:
                 res = self.registerService(dad)
                 cont=cont+1
          if not res:
              return OrganizationalExceptions.DFException
          else: return True

    def createRoom(self):
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        p = Presence(frm=self.name+"@"+self.muc_name+"/"+self.nick)
        t1 = Behaviour.MessageTemplate(p)
        b=self.CreateRoomBehaviour(ID,self.muc_name,self.name,self.nick,self.contentLanguage,self.type,self.goalList)
        self.addBehaviour(b, t1)
        b.join()
        return b.result

    class CreateRoomBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,ID,muc_name,roomname,nick,contentLanguage,type,goal):
            Behaviour.OneShotBehaviour.__init__(self)
            self.result = False
            self.ID=ID
            self.nick=nick
            self.muc_name=muc_name
            self.name=roomname
            self.contentLanguage=contentLanguage
            self.type=type
            self.goal=goal

        def _process(self):
            p = Presence(to=self.name+"@"+self.muc_name+"/"+self.nick)
            x = Protocol("x", xmlns="http://jabber.org/protocol/muc")
            p.addChild(node=x)
            self.myAgent.jabber.send(p)
            msg=self._receive(True,10)
            if msg:
                if msg.getAttr("type")=="error":
                    print "Room creation is restricted"
                    self.result= False
                    return
            else:
                    self.result= False
                    return
            template= Iq(frm=self.name+"@"+self.muc_name, attrs={"id":self.ID})
            t = Behaviour.MessageTemplate(template)
            self.setTemplate(t)
            iq = Iq(to=self.name+"@"+self.muc_name,typ='get', attrs={"id":self.ID})
            query = Protocol('query',xmlns="http://jabber.org/protocol/muc#owner")
            iq.addChild(node=query)
            self.myAgent.jabber.send(iq)
            msg = self._receive(True,10)
            #para descartar los presence anteriores
            while msg and msg.getName()!="iq":
                msg = self._receive(True,10)

          #setting room configuration
            if not msg or msg.getAttr("type")=="error":
                print "No configuration is possible: "
                self.result= False
                return
            #falta por revisar!!!!
            iq = Iq(to=self.name+"@"+self.muc_name,typ='set', attrs={"id":self.ID})
            query = Protocol('query',xmlns="http://jabber.org/protocol/muc#owner")
            x=Node(tag="x", attrs={"xmlns":"jabber:x:data"," type":"submit"})
            resquery=msg.getQueryChildren()[0] #nos quedamos con el hijo de query
            if resquery: items = resquery.getTags("field")
            if resquery==None:
                print "No configuration is possible"
                self.result= False
            for item in items:
                value=None
                if item.getAttr("var") == "muc#roomconfig_lang":
                    value=self.contentLanguage
                if item.getAttr("var") == "muc#roomconfig_roomdesc":
                    value=self.type
                if item.getAttr("var") == "muc#roomconfig_roomtype":
                    value=self.name
                if item.getAttr("var") == "muc#roomconfig_roomname":
                    value=self.name
                if item.getAttr("var") == "muc#roomconfig_presencebroadcast":
                    value="moderator"
                if item.getAttr("var") == "muc#roomconfig_persistentroom":
                    value="1"
                if item.getAttr("var") == "muc#roomconfig_publicroom":
                    value="1"
                if item.getAttr("var") == "muc#roomconfig_moderatedroom":
                    value="1"
                if item.getAttr("var") == "muc#roomconfig_membersonly":
                    value="0"
                if item.getAttr("var") == "muc#roomconfig_passwordprotectedroom":
                    value="0"
                if item.getAttr("var") == "muc#roomconfig_whois":
                    value="moderators"
                if item.getAttr("var") == "muc#roomconfig_changesubject":
                    if self.type!="Flat":
                        value="0"
                    else:
                        value="1"
                if value:
                    node=Node(tag="field", attrs={"var":item.getAttr("var")})
                    valnode=Node(tag="value")
                    valnode.addData(value)
                    node.addChild(node=valnode)
                    x.addChild(node=node)
            query.addChild(node=x)
            iq.addChild(node=query)
            self.myAgent.jabber.send(iq)
            msg = self._receive(True,10)
            if msg and msg.getAttr("type")=="result": #comprobar mejor el mensaje que se devuelve
                #modifying the Room Subject
                m = Message(to=self.name+"@"+self.muc_name, typ="groupchat")
                sub = Node(tag="subject")
                sub.addData(str(self.goal))
                m.addChild(node=sub)
                self.myAgent.jabber.send(m)
                #añadimos al DF como owner de la organizacion
                iq = Iq(to=self.name+"@"+self.muc_name,typ='set', attrs={"id":self.ID})
                query = Protocol('query',xmlns="http://jabber.org/protocol/muc#admin")
                item= Node(tag="item", attrs={"affiliation":"owner","jid":self.myAgent.getDF().getName()})
                query.addChild(node=item)
                iq.addChild(node=query)
                self.myAgent.jabber.send(iq)
                self.result= True
            else:
                self.result= False

    class PresenceBehaviour(Behaviour.Behaviour):
        def __init__(self):
            Behaviour.Behaviour.__init__(self)

        def _process(self):
            msg = self._receive(True)
            if msg:
                if msg.getType()=="unavailable":
                    nick=str(msg.getFrom()).split("/")[1]
                    delete=[]
                    for a in self.myAgent.agentList:
                        if a["Nick"]==nick:
                            delete.append(a)
                    for d in delete:
                        self.myAgent.agentList.remove(d)
                else:
                    jid=str(msg.getTag("x").getTag("item").getAttr("jid")).split("/")[0]
                    nick=str(msg.getFrom()).split("/")[1]
                    if jid!=None and jid!="None":
                        agent={"Aid":jid,"Nick":nick,"Role":[]}
                        if str(agent["Aid"])!=str(self.myAgent.getAID().getName()):
                            self.myAgent.agentList.append(agent)

    def updateUnits(self):
        ans=ACLMessage.ACLMessage()
        ans.setPerformative("inform")
        ans.setSender(self.getAID())
        ans.setOntology("x:spade:manager")
        ans.setContent("Update:"+str({"RoleList":self.orgRoleList}))
        if self.unitList!=[]:
            for u in self.unitList:
                ans.addReceiver(u["Manager"])
            self.send(ans)

    class ManagerBehaviour(Behaviour.Behaviour):
        def __init__(self):
            Behaviour.Behaviour.__init__(self)

        def _process(self):
            #¿Quien puede modificarla?????
            mens=self._receive(True,1)
            if mens:
                if mens.getPerformative()=="inform":
                    content=mens.getContent().partition(":")
                    if content[0]=="Update":
                        info=eval(content[2])
                        self.myAgent.orgRoleList=info["RoleList"]
                        self.myAgent.updateRoleInformation()
                        self.myAgent.updateUnits()
                    if content[0]=="StrucuralInformation":
                        info=eval(content[2])
                        self.myAgent.orgRoleList=info["RoleList"]
                    elif content[0]=="Unit":
                        content=mens.getContent().split(":")
                        #print "La nueva unidad es",{"Unit":str(content[1]),"Manager":mens.getSender()}
                        self.myAgent.unitList.append({"Unit":str(content[1]),"Manager":mens.getSender()})
                    elif content[0]=="Destroy":
                        self.myAgent.destroy()
                if mens.getPerformative()=="request":
                    content=mens.getContent()
                    if str(content)=="StrucuralInformation":
                        ans=ACLMessage.ACLMessage()
                        ans.setPerformative("inform")
                        ans.setSender(self.myAgent.getAID())
                        ans.setOntology("x:spade:manager")
                        ans.addReceiver(mens.getSender())
                        ans.setContent("StrucuralInformation:"+str({"RoleList":self.myAgent.orgRoleList}))
                        self.myAgent.send(ans)

    def updateRoleInformation(self):
        types={"Communication":2,"Knowledge":1,"Authority":3}
        roleNames=[]
        for r in self.orgRoleList:
            roleNames.append(r["Role"])
        for r in self.roleList:
            if r["Role"] not in roleNames:
                self.roleList.remove(r)

    def allow(self,name,op,info1=None,info2=None,info3=None):
        update=False
        if name=="Role":
            roleNames=[]
            for r in self.roleList:
                roleNames.append(r["Role"])
            if op=="Add":
                if info1==None or info2==None:return False
                for p in info2:
                    if p not in roleNames:
                        return False
                rol={"Role":info1,"Parent":info2}
                delete=[]
                for r in self.roleList:
                    if info1==r["Role"]:
                        delete.append(r)
                for d in delete:
                    self.roleList.remove(d)
                self.roleList.append(rol)
                update=True
            if op=="Remove":
                if info1==None: return False
                exists=False
                for r in self.roleList:
                    if r["Role"]==info1:
                        exists=True
                        aux=r
                if not exists:return False
                self.roleList.remove(aux)
                deleted=aux["Role"]
                for r in self.roleList:
                        if deleted in r["Parent"]:
                          r["Parent"].remove(deleted)
                delete=[]
                for l in self.roleLinkList:
                    if l["Role1"]== deleted or l["Role2"]== deleted:
                        delete.append(l)
                for d in delete:
                    self.roleLinkList.remove(d)
                update=True
            if op=="Get":
                return True
        if name=="Permision":
            if op=="Creation" or op=="Goal":
                pass
            elif op=="Destroy":
                self.destroy()
            else:
                return False
        if update:self.updateUnits()
        return True

    def destroy(self):
      #eliminar del DF
        dad = DF.DfAgentDescription()
        dad.setAID(self.getAID())
        self.deregisterService(dad)
        ans=ACLMessage.ACLMessage()
        ans.setPerformative("inform")
        ans.setSender(self.getAID())
        ans.setOntology("x:spade:manager")
        ans.setContent("Destroy")
        if self.unitList!=[]:
            for u in self.unitList:
                ans.addReceiver(u["Manager"])
            self.send(ans)
        ID="".join([string.ascii_letters[int(random.randint(0,len(string.ascii_letters)-1))] for a in range(5)])
        p = Iq(frm=self.name+"@"+self.muc_name, attrs={"id":ID})
        t1 = Behaviour.MessageTemplate(p)
        b=self.DestroyBehaviour(self.muc_name,self.name,ID)
        self.addBehaviour(b, t1)
        b.join()
        self._shutdown()



    class DestroyBehaviour(Behaviour.OneShotBehaviour):
        def __init__(self,muc_name,roomname,ID):
            Behaviour.OneShotBehaviour.__init__(self)
            self.ID=ID
            self.muc_name=muc_name
            self.name=roomname

        def _process(self):
          iq = Iq(to=self.name+"@"+self.muc_name,typ='set', attrs={"id":self.ID})
          query = Protocol('query',xmlns="http://jabber.org/protocol/muc#owner")
          item= Node(tag="destroy")
          query.addChild(node=item)
          iq.addChild(node=query)
          self.myAgent.jabber.send(iq)

    def intersection(self,l1,l2):
        result=[]
        for i in l1:
            if i in l2:
                result.append(i)
        return result


def checkGoal(goalList):
    #falta por implementar
      return True

def checkType(type):
    types=["Flat","Team","Hierarchy","Bureaucracy","Matrix","Federation","Coalition","Congregation"]
    if type in types:
       return True
    return False

def checkTypes(orgType,unitType):
    if orgType=="Flat":
      return True
    if orgType=="Team" and unitType=="Team":
      return True
    if orgType=="Hierarchy" and unitType=="Hierarchy":
      return True
    if orgType=="Bureaucracy" and unitType=="Hierarchy":
      return True
    if orgType=="Matrix" and unitType=="Hierarchy":
      return True
    if orgType=="Federation" and unitType=="Hierarchy":
      return True
    if orgType=="Coalition" and unitType=="Team":
      return True
    if orgType=="Congregation" and unitType=="Hierarchy":
      return True
    if orgType=="Congregation" and unitType=="Team":
      return True
    if orgType=="Congregation" and unitType=="Flat":
      return True
    return False

"""